<?php
class UserDao
{
	private $_tgUser;
	private $_tgUserAttr;
	private $_tgUserAttrConf;
	private $_tgUserAttrConfOpt;

	public function __construct()
	{
		$this->_tgUser = Db::newDbTable('user');
		$this->_tgUserAttr = Db::newDbTable('user_attr');
		$this->_tgUserAttrConf = Db::newDbTable('user_attr_conf');
		$this->_tgUserAttrConfOpt = Db::newDbTable('user_attr_conf_opt');
	}

	private function _getAttrConfOpts($attrId, $includeDisabled = false)
	{
		$condition = array(
			"where" => array(
				"expression" => "attr_id = :attr_id", 
				"value" => array("attr_id" => $attrId)
		),
			"orderby" => "display_order"
			);
			if (!$includeDisabled)
			{
				$condition["where"]["expression"] .= " AND disabled = 0";
			}
			return $this->_tgUserAttrConfOpt->fetchRows($condition);
	}

	public function getUserAttrConfs($onlyForReader = false, $includeDisabled = false)
	{
		$confs = array();
		/*
		 *@todo cache
		 */
		$condition["orderby"] = "display_order";
		if (!$includeDisabled)
		{
			$condition["where"]["expression"] = "disabled = 0";
			if ($onlyForReader)
			{
				$condition["where"]["expression"] .= " AND hidden_for_reader = 0";
			}
		}
		foreach($this->_tgUserAttrConf->fetchRows($condition) as $row)
		{
			$confs[] = $this->getUserAttrConf($row['id']);
		}
		return $confs;
	}

	public function getUserAttrConf($attrId)
	{
		/*
		 *@todo cache
		 */
		$row = $this->_tgUserAttrConf->fetch($attrId);
		$row['options'] = $this->_getAttrConfOpts($attrId, true);
		if (strlen($row["default_value"]))
		{
			$row["default_value"] = unserialize($row["default_value"]);
		}
		if (strlen($row["validator_conf"]))
		{
			$row["validator_conf"] = unserialize($row["validator_conf"]);
		}
		return $row;
	}

	private function _updateUserAttrConfOpt($attrId, $options)
	{
		$this->_tgUserAttrConfOpt->deleteRows(array("expression" => "attr_id = :attr_id", "value" => array("attr_id" => $attrId)));
		foreach($options as $option)
		{
			$option["attr_id"] = $attrId;
			$this->_tgUserAttrConfOpt->insert($option);
		}
	}

	public function updateUserAttrConf($attrConf)
	{
		if (isset($attrConf["validator_conf"]))
		{
			$attrConf["validator_conf"] = serialize($attrConf["validator_conf"]);
		}
		if (isset($attrConf["default_value"]))
		{
			$attrConf["default_value"] = serialize($attrConf["default_value"]);
		}
		if($this->_tgUserAttrConf->update($attrConf['id'], $attrConf))
		{
			/*
			 *@todo cache
			 */
			if (isset($attrConf["options"]))
			{
				$this->_updateUserAttrConfOpt($attrConf['id'], $attrConf["options"]);
			}
			return 1;
		}
	}

	public function insertUserAttrConf($attrConf)
	{
		$attrConf["validator_conf"] = serialize($attrConf["validator_conf"]);
		$attrConf["default_value"] = serialize($attrConf["default_value"]);
		if($attrId = $this->_tgUserAttrConf->insert($attrConf))
		{
			/*
			 *@todo cache
			 */
			if (isset($attrConf["options"]))
			{
				$this->_updateUserAttrConfOpt($attrId, $attrConf["options"]);
			}
			return $attrId;
		}
	}

	public function getUserByUsername($username)
	{
		$userRows = $this->_tgUser->fetchRows(
		array(
      "where" => array(
				"expression" => "username = :username",
				"value" => array("username" => $username)
		)));
		return $userRows ? $userRows[0] : $userRows;
	}

	public function getUserByEmail($email)
	{
		$userRows = $this->_tgUser->fetchRows(
		array(
        "where" => array(
          "expression" => "email = :email",
          "value" => array("email" => $email)
		)));
		return $userRows ? $userRows[0] : $userRows;
	}
	
	private function insertUserAttr($user)
	{
		if (isset($user['attr']) && is_array($user['attr']))
		{
			$revision = time();
			foreach ($user['attr'] as $attrId => $attrValue)
			{
				$userAttr = array();
				$userAttr['user_id'] = $user["id"];
				$userAttr['revision'] = $revision;
				$userAttr['attr_id'] = $attrId;
				$userAttrConf = $this->getUserAttrConf($attrId);
				$userAttr['attr_value'] = in_array($userAttrConf["form_item_type"], array("checkbox", "multiple_select")) ? serialize($attrValue) : $attrValue;
				$this->_tgUserAttr->insert($userAttr);
			}
		}
	}

	public function insertUser($user)
	{
		$user["signup_ip"] = ip2long($user["signup_ip"]);
		if ($userId = $this->_tgUser->insert($user))
		{
			$user["id"] = $userId;
			$this->insertUserAttr($user);
		}
		return $userId;
	}

	public function updateUser($user)
	{
		if ($rowCount = $this->_tgUser->update($user["id"], $user))
		{
			$this->insertUserAttr($user);
		}
		return $rowCount;
	}

	public function getUsers($condition = null)
	{
		if (isset($condition["where"]["value"]["signup_ip"]))
		{
			$condition["where"]["value"]["signup_ip"] = ip2long($condition["where"]["value"]["signup_ip"]);
		}
		return $this->_tgUser->fetchRows($condition);
	}

	public function getUser($id, $onlyForReader = false)
	{
		if($user = $this->_tgUser->fetch($id))
		{
			$userAttrs = $this->_tgUserAttr->fetchRows(
			array(
	      		"fields" => "attr_id, attr_value",
	      		"where" => array(
	        		"expression" => "user_id = :user_id",
	        		"value" => array("user_id" => $id)
			),
				"orderby" => "revision DESC"
				));
				$userAttrConfs = $this->getUserAttrConfs($onlyForReader);
				foreach ($userAttrConfs as $userAttrConf)
				{
					foreach ($userAttrs as $userAttr)
					{
						if ($userAttr["attr_id"] == $userAttrConf["id"])
						{
							$userAttrConf["user_value"] = in_array($userAttrConf["form_item_type"], array("checkbox", "multiple_select")) ? unserialize($userAttr["attr_value"]) : $userAttr["attr_value"];
							$userAttrConf["default_value"] = $userAttrConf["user_value"];
							break;
						}
					}
					$user["attr"][] = $userAttrConf;
				}
		}
		return $user;
	}
}